<?php

namespace web\api\controller;

class InterfaceAuthentication extends \web\common\controller\Controller {

	protected $apikey = 'E7D7DD8C63142C835B6C8CB4C544755E';
	protected $sign_passtime = 3;

	/**
	 * 全局redis缓存
	 * @var type
	 */
	protected $globalCache = null; //think\cache\driver\Redis

	/**
	 * 数据缓存
	 * @var type
	 */
	protected $dataCache = null;
	protected $base_url = 'http://www.douxin.pro';


	protected function _initialize() {
		header("Access-Control-Allow-Origin:*");
		$this->bindCache($this->request); //绑定缓存实例
		$this->globalCache = $this->request->__get('global_cache'); //实例化
		$this->dataCache = $this->request->__get('data_cache');
		if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
			return true;
		}
		//签名验证
		if (!empty($_POST)) {
			if(!isset($_POST['sign'])) $this->failJSON('签名错误');
			$this->signValue = $_POST['sign']; //取出签名
			$this->paramData = $this->getPostData();
			$this->checkSign();
		} else {
			$this->failJSON('签名错误');
		}
	}

	/**
	 * 设置当前请求绑定的缓存对象实例--redis
	 * @param type $request
	 */
	private function bindCache(&$request) {
		if (!$request->__isset('data_cache')) {
			$dataCache = \think\Cache::connect(\think\Config::get('data_cache'));
			$request->bind('data_cache', $dataCache);
		}
		if (!$request->__isset('global_cache')) {
			$globalCache = \think\Cache::connect(\think\Config::get('global_cache'));
			$request->bind('global_cache', $globalCache);
		}
	}

	/**
	 * 获取全局缓存数据
	 * @param type $key
	 * @return type
	 */
	protected function getGlobalCache($key = null) {
		$data = null;
		if ($this->globalCache) {
			if (empty($key)) {
				return $this->failJSON(lang("API_LOGIN_FAIL"));
			}
			$data = $this->globalCache->get($key);
		}
		return $data;
	}

	/**
	 * 设置全局缓存数据
	 * @param type $data
	 * @param type $key
	 * @param type $expire
	 */
	protected function setGlobalCache($data, $key = null, $expire = null) {
		if ($this->globalCache) {
			if (empty($key)) {
				$key = $this->getCacheKey();
			}

			return $this->globalCache->set($key, $data, $expire);
		}
	}

	/**
	 *
	 * 检测签名
	 */
	protected function checkSign() {
		if (!isset($this->paramData['ts'])) {
			$this->failJSON(lang('API_WRONG_SIGN'));
		}
		if ((time() - $this->paramData['ts']) > $this->sign_passtime) {
			$this->failJSON(lang('API_TIMEOUT'));
		}
		$sign = $this->makeSign();
		if ($this->signValue === $sign) {
			return true;

		} else {
			$this->failJSON(lang('API_WRONG_SIGN'));
		}
	}


	/**
	 * 生成签名
	 */
	private function makeSign() {
		return strtoupper(md5($this->apikey.$this->paramData['ts']));
	}

	/**
	 * 格式化参数格式化成url参数(字典排序后重组)
	 */
	private function toUrlParams() {
		$buff = '';
		foreach ($this->paramData as $k => $v) {
			if ($v != '' && !is_array($v)) {
				if (preg_match('/[\x80-\xff]./', $v)) {
					$buff .= $k . '=' . urldecode($v) . '&';
				} else {
					$buff .= $k . '=' . $v . '&';
				}

			}
		}
		$buff = trim($buff, '&');
		return $buff;
	}

	/**
	 * 获取参数值.
	 * @param type $name
	 * @param type $no_null 不能为空
	 * @return type
	 */
	protected function getParamVal($name, $no_null = true, $type = '') {
		$data = $this->paramData[$name];
		if ($no_null && $data == null) {
			$this->failJSON(lang('API_PARAM') . $name . '！');
		} else {
			if ($data != null) {
				if ($type == 'int') {
					if (!is_numeric($data)) {
						$this->failJSON('参数' . $name . '类型有误!');
					} else {
						$data = intval($data);
					}

				} else if ($type == 'float') {
					if (!is_numeric($data)) {
						$this->failJSON('参数' . $name . '类型有误！');
					} else {
						$data = floatval($data);
					}

				} else if ($type == 'double') {
					if (!is_numeric($data)) {
						$this->failJSON('参数' . $name . '类型有误！');
					} else {
						$data = doubleval($data);
					}

				}
			}
			$this->paramData[$name] = $data;
			return $data;
		}
	}

	/**
	 * 获取POST提交的数据。
	 * @return type
	 */
	protected function getPostData() {
		$data = array();
		if (isset($_POST)) {
			$post_data = $_POST;
			$data = !empty($post_data) ? $post_data : array();
			unset($data['sign']);
			$data['api_key'] = $this->apikey;
		} else {
			return $this->failJSON('post data is empty');
		}
		return $data;
	}

	/**
	 * 输出错误JSON信息。
	 * @param type $message
	 */
	protected function failJSON($message, $code = 400) {
		$message = lang($message);
		$jsonData = array('code' => $code, 'data' => $message);
		$json = json_encode($jsonData, true);
		echo $json;
		exit;
	}

	/**
	 * 输出成功JSON信息
	 * @param type $data
	 */
	protected function successJSON($data = NULL) {
		$jsonData = array('code' => 0, 'data' => $data);
		$json = json_encode($jsonData, 1);
		echo $json;
		exit;
	}

	protected function cacheLock($lockKey, $locktime = 2) {
		$redis = (\think\Cache::connect(\think\Config::get('global_cache')))->getHandler();
		$randValue = rand(10000, 99999); //lock
		$lock = $redis->set($lockKey, $randValue, ['NX', 'EX' => $locktime]);
		if (!$lock) {
			return $this->failJSON('请不要重复请求');
		}

		$script = '
            if redis.call("get",KEYS[1]) == ARGV[1] then
                return redis.call("del",KEYS[1])
            else
                return 0
            end
        ';
		return ['redis' => $redis, 'script' => $script, 'data' => [$lockKey, $randValue]];
	}

}
